﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace DuplicationDetection
{
    public class DiffUtility
    {
        public List<string> Folders = new List<string>();

        public List<string> FilterFolders()
        {
            // Filter duplicated Folders
            List<string> folders = new List<string>();
            folders.AddRange(Folders);

            folders.Sort();
            for (int i = 0; i < folders.Count - 1; i++)
            {
                if (folders[i].StartsWith(folders[i+1].TrimEnd(new char[]{'\\'})+@"\"))
                {
                    folders.RemoveAt(i + 1);
                }
                else if (folders[i + 1].StartsWith(folders[i].TrimEnd(new char[] { '\\' }) + @"\"))
                {
                    folders.RemoveAt(i);
                }
            }
            // Filter excluded folders
            // TODO, add exclude logic here.

            return folders;
        }
        public void AddFolder(string folderName)
        {
            if (Directory.Exists(folderName))
            {
                Folders.Add(folderName);                
            }
        }
        void MergeDuplicated(ref Dictionary<FileInfoEx, List<FileInfoEx>> result, FileInfoEx fi)
        {
            bool found = false;
            foreach (var item in result.Keys)
            {
                if (item.Equals(fi))
                {
                    if (result[item] == null)
                    {
                        result[item] = new List<FileInfoEx>();
                    }
                    result[item].Add(fi);
                    found = true;
                    break;
                }
            }

            if (!found)
            {
                result[fi] = null;
            }
        }
        private void MergeFolder(ref Dictionary<FileInfoEx, List<FileInfoEx>> result, string folderName)
        {
            // Process files
            foreach (var item in Directory.GetFiles(folderName))
            {
                var fi = FileInfoEx.CreateFileInfo(Path.GetFullPath(item));
                MergeDuplicated(ref result, fi);
            }

            foreach (string item in Directory.GetDirectories(folderName))
            {
                MergeFolder(ref result, item);
            }
        }

        Dictionary<FileInfoEx, List<FileInfoEx>> results = null;
        public void DuplicationDetect()
        {
            Dictionary<FileInfoEx, List<FileInfoEx>> result = new Dictionary<FileInfoEx, List<FileInfoEx>>();
            foreach (string folder in this.FilterFolders())
            {
                MergeFolder(ref result, folder);            
                
            }

            this.results = result;
        }

        public Dictionary<FileInfoEx, List<FileInfoEx>> DumpDuplication()
        {
            Dictionary<FileInfoEx, List<FileInfoEx>> result = new Dictionary<FileInfoEx, List<FileInfoEx>>();
            foreach (var item in this.results)
            {
                if (item.Value != null)
                {
                    result.Add(item.Key,item.Value);
                }
            }
            return result;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            DiffUtility du = new DiffUtility();
            du.AddFolder(@"E:\testdata\test");
            du.AddFolder(@"E:\testdata\test - Copy");
            du.AddFolder(@"E:\testdata\TEC");

            du.DuplicationDetect();

            foreach (var item in du.DumpDuplication())
            {
                Console.WriteLine(item.Key.FullPath);
                foreach (var dup in item.Value)
                {
                    Console.WriteLine("\t"+dup.FullPath);
                }
            }

            Console.ReadLine();
        }
    }
}
